package org.cuit.echo.seon.example.factory;

import org.cuit.echo.seon.example.dao.DepartmentDao;
import org.cuit.echo.seon.example.dao.UserDao;
import org.cuit.echo.seon.example.entity.Department;
import org.cuit.echo.seon.example.entity.User;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.Properties;

/**
 * @author Seon
 * @version 1.0
 * @since 2024-09-10
 */
public class DataAccess {
    private static final String ASSEMBLY_NAME = "org.cuit.echo.seon.example.dao.impl.";
    private static final String SUFFIX = "DaoImpl";
    private static String db = null;

    /**
     * 根据类名生成Dao的实现类全名
     */
    private static String getClassName(String entityName) {
        return ASSEMBLY_NAME + getDb() + entityName + SUFFIX;
    }

    /**
     * 懒加载DB信息
     */
    private static String getDb() {
        if (db == null) {
            Properties prop = new Properties();
            try (InputStream is = DataAccess.class.getClassLoader().getResourceAsStream("db_config.properties")) {
                if (is == null) {
                    throw new RuntimeException("请配置DB信息");
                }
                prop.load(is);
                db = prop.getProperty("db");
            } catch (IOException e) {
                throw new RuntimeException("无法加载数据库配置文件", e);
            }
        }
        return db;
    }

    /**
     * 创建通用Dao实例
     */
    private static <T> T createDao(Class<T> daoClass, String entityName) {
        String className = getClassName(entityName);
        try {
            return daoClass.cast(Class.forName(className).getDeclaredConstructor().newInstance());
        } catch (InstantiationException | IllegalAccessException | InvocationTargetException |
                 NoSuchMethodException | ClassNotFoundException e) {
            throw new RuntimeException("无法创建Dao实例: " + className, e);
        }
    }

    public static UserDao createUserDao() {
        return createDao(UserDao.class, User.class.getSimpleName());
    }

    public static DepartmentDao createDepartmentDao() {
        return createDao(DepartmentDao.class, Department.class.getSimpleName());
    }
}
